package com.joysuch.wwyt.bp.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.zlg.common.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.joysuch.wwyt.bp.bean.BpDeviceFacilityDetectRecordBean;
import com.joysuch.wwyt.bp.bean.facility.BpProductionFacilityListBean;
import com.joysuch.wwyt.bp.bean.facility.BpProductionFacilityTypeDto;
import com.joysuch.wwyt.bp.entity.BpDeviceFacilityDetectRecord;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.bp.repository.BpDeviceFacilityDetectRecordDao;
import com.joysuch.wwyt.bp.service.BpDeviceFacilityDetectRecordService;
import com.joysuch.wwyt.bp.service.BpProductionFacilityService;
import com.joysuch.wwyt.bp.service.BpProductionFacilityTypeService;
import com.joysuch.wwyt.common.entity.CommonIndexNotify;
import com.joysuch.wwyt.common.enums.CommonIndexNotifyTypes;
import com.joysuch.wwyt.common.service.CommonIndexNotifyService;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.DateTimeUtil;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.Assert;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author ZhangDong
 * @Date 2021/1/12 15:22
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class BpDeviceFacilityDetectRecordServiceImpl implements BpDeviceFacilityDetectRecordService {

    @Autowired
    private BpDeviceFacilityDetectRecordDao dao;
    @Autowired
    private BpDepartDao departDao;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private BpProductionFacilityService bpProductionFacilityService;
    @Autowired
    private BpProductionFacilityTypeService bpProductionFacilityTypeService;
    @Autowired
    private CommonIndexNotifyService commonIndexNotifyService;

    @Override
    public ResultBean save(BpDeviceFacilityDetectRecordBean bean) {
        Long id = bean.getId();
        BpDeviceFacilityDetectRecord record;
        if (id == null) {
            record = new BpDeviceFacilityDetectRecord();
        } else {
            record = dao.findById(id).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
        }
        BeanUtils.copyProperties(bean, record);
        //附件
        BaseAttachmentBean attachmentBean = bean.getAttachmentBean();
        record.setAttachmentJson(attachmentBean == null ? null : JSON.toJSONString(attachmentBean));
        BpDeviceFacilityDetectRecord save = dao.save(record);
        //保存后查看当前设备的类型是否设置了到期提醒，如果有则并且此次记录是最新的记录新增到期提醒记录
        BpProductionFacilityListBean productionFacility = bpProductionFacilityService.findById(save.getDeviceFacilityId());
        if (productionFacility != null && productionFacility.getType() != null && productionFacility.getDetectDays() != null /*&& save.getDetectValidityDate().getTime() > System.currentTimeMillis()*/) {
            BpProductionFacilityTypeDto dto = bpProductionFacilityTypeService.getById(productionFacility.getType());
            if (dto != null) {
                if (dto.getExpireRemindOrNot() != null && dto.getExpireRemindOrNot() == 1) {
                    LocalDateTime localDateTime = DateTimeUtil.date2LocalDateTime(save.getDetectValidityDate()).minusDays(Integer.valueOf(dto.getRemindType()));
                    Date date = DateTimeUtil.localDateTime2Date(localDateTime);
                    //如果此次填写的信息需要未来或者今天提醒，并且此记录不是最新的记录则无需新增到期提醒记录
                    if (!date.before(new Date()) && !isLastRecord(save)){
                        return ResultBean.success(save.getId());
                    }
                    //如果是提醒未来的消息并且是最新的记录则去除未来还未发出的通知
                    if (date.after(new Date())){
                        bpProductionFacilityService.removeRemindNotify(productionFacility.getId(), CommonIndexNotifyTypes.PRODUCTION_FACILITY_DETECT.getType());
                    }
                    bpProductionFacilityService.remindNotify(productionFacility.getName(), productionFacility.getId(), save.getId(), productionFacility.getType(), date, save.getDetectValidityDate(), CommonIndexNotifyTypes.PRODUCTION_FACILITY_DETECT.getType(), "设备检测");
                }
            }
        }
        return ResultBean.success(save.getId());
    }

    @Override
    public ResultBean page(Pageable pageable, Long deviceFacilityId) {
        Assert.notNull(deviceFacilityId, "deviceFacilityId cannot be null");
        pageable = PageDataUtils.addOrderByDesc(pageable, "id");
        Page<BpDeviceFacilityDetectRecord> page = dao.findByDeviceFacilityId(deviceFacilityId, pageable);
        List<BpDeviceFacilityDetectRecord> list = page.getContent();
        List<BpDeviceFacilityDetectRecordBean> resultList = covertList(list);
        return ResultBean.pageData(resultList, page.getTotalElements());
    }

    @Override
    public ResultBean getById(Long id) {
        BpDeviceFacilityDetectRecord record = dao.findById(id).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
        BpDeviceFacilityDetectRecordBean bean = new BpDeviceFacilityDetectRecordBean();
        BeanUtils.copyProperties(record, bean);
        List<Long> userIdList = new ArrayList<>(3);
        userIdList.add(bean.getInnerUserId());
        userIdList.add(bean.getRegisterUserId());
        userIdList = userIdList.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
        Map<Long, String> userMap = baseUserDao.findAllById(userIdList).stream().collect(Collectors.toMap(r -> r.getId(), r -> r.getRealName()));
        //部门
        bean.setDepartName(departDao.findDepartNameById(bean.getDepartId()));
        completeInfo(record, bean, userMap);
        return ResultBean.success(bean);
    }

    /**
     * 删除
     *
     * @param recordId
     */
    @Override
    public void deleteById(Long recordId) {
        dao.deleteById(recordId);
        //该条记录所绑定的到期提醒也要删掉
        List<CommonIndexNotify> list = commonIndexNotifyService.getByTypeAndRecordId(CommonIndexNotifyTypes.PRODUCTION_FACILITY_DETECT.getType(), recordId);
        if (CollectionUtils.isNotEmpty(list)) {
            for (CommonIndexNotify notify : list) {
                if (notify != null && notify.getRemindedOrNot() == 0) {
                    commonIndexNotifyService.cancelAndRemove(notify);
                    commonIndexNotifyService.delete(notify.getId());
                }
            }
        }
    }

    private void completeInfo(BpDeviceFacilityDetectRecord record, BpDeviceFacilityDetectRecordBean bean, Map<Long, String> userMap) {
        //内部检测人
        bean.setInnerUserName(userMap.getOrDefault(bean.getInnerUserId(), ""));
        //登记人
        bean.setRegisterUserName(userMap.getOrDefault(bean.getRegisterUserId(), ""));
        //附件
        String json = record.getAttachmentJson();
        bean.setAttachmentBean(json == null ? null : JSON.parseObject(json, BaseAttachmentBean.class));
    }

    private List<BpDeviceFacilityDetectRecordBean> covertList(List<BpDeviceFacilityDetectRecord> list) {
        List<Long> departIdList = list.stream().map(r -> r.getDepartId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<Long> innerUserIdList = list.stream().map(r -> r.getInnerUserId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        List<Long> registerIdList = list.stream().map(r -> r.getRegisterUserId()).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        innerUserIdList.addAll(registerIdList);
        innerUserIdList = innerUserIdList.stream().distinct().collect(Collectors.toList());
        Map<Long, String> userMap = baseUserDao.findAllById(innerUserIdList).stream().collect(Collectors.toMap(r -> r.getId(), r -> r.getRealName()));
        Map<Long, String> departMap = departDao.findAllById(departIdList).stream().collect(Collectors.toMap(r -> r.getId(), r -> r.getName()));
        List<BpDeviceFacilityDetectRecordBean> resultList = new ArrayList<>(list.size());
        for (BpDeviceFacilityDetectRecord record : list) {
            BpDeviceFacilityDetectRecordBean bean = new BpDeviceFacilityDetectRecordBean();
            BeanUtils.copyProperties(record, bean);
            //部门
            bean.setDepartName(departMap.getOrDefault(bean.getDepartId(), ""));
            //内部检测人
            completeInfo(record, bean, userMap);
            resultList.add(bean);
        }
        return resultList;
    }

    /**
     * 判断此条检查记录是否是该设备最新的记录
     * @param save
     * @return
     */
    private boolean isLastRecord(BpDeviceFacilityDetectRecord save){
        Long id = save.getId();
        Long deviceFacilityId = save.getDeviceFacilityId();
        Date detectDate = DateTimeUtil.localDate2Date(save.getDetectDate());
        Long lastRecord = dao.isLastRecord(id, deviceFacilityId, detectDate);
        return lastRecord == 0;
    }

}
